#include <stdio.h>
#include <iostream>

#ifdef SYPX_MEMCHECK
#include "mmgr.h"
#endif

#include "Base.h"
#include "Texture.h"
#include "Engine.h"
#include "ResourceManager.h"
#include "ErrorLogger.h"
#include <png.h>


namespace SypX
{
	Texture::Texture(void):texID(0)
	{
	}
	
	UInt& Texture::getTexIDRef()
	{
		return texID;
	}
	
	UInt Texture::getWidth()
	{
		return width;
	}
	
	UInt Texture::getHeight()
	{
		return height;
	}
	
	UByte Texture::getBpp()
	{
		return bpp;
	}
	
	UByteArray& Texture::getDataRef()
	{
		return data;
	}

	Texture::~Texture(void)
	{
		if(texID)
		{	
			Engine::getSingleton()->getRenderer()->deleteTexture(this);
		}
		
	}

	TextureFormat Texture::getDataFormat()
	{
		return texFormat;
	}

	TextureFormat Texture::getInternalFormat()
	{
		return internalTexFormat;
	}

	void Texture::setFormats(TextureFormat dataFormat, TextureFormat internalFormat)
	{
		internalTexFormat = internalFormat;
		texFormat = dataFormat;
	}

	void Texture::setWidth(UInt w)
	{
		width = w;
	}

	void Texture::setHeight(UInt h)
	{
		height = h;
	}

	void Texture::submitToGPU()
	{		
		Engine::getSingleton()->getRenderer()->createTexture(this);
	}

	Texture* Texture::loadFromFile(const String &file)
	{	
		//You have to be a real blockhead to load same file(.png) as texture and something else(mesh/sprite/etc..)
		Texture* tex = static_cast<Texture*>(ResourceManager::getSingleton()->checkResource(file));
		if(tex)
		{//Resource already loaded
			return tex;
		}
		
		tex = new Texture();
		tex->setFileName(file);
		String path = Engine::getFilePath(file);
		ErrorLogger::getLogger()<<path<<"\n";
		FILE *fp = fopen(path.c_str(), "rb");
		int number = 8;
		UByte header[8];

		if (!fp)
		{
			ErrorLogger::getLogger()<<"Error: file not found : "<<file<<" \n";
		}
		fread(header, 1, number, fp);
		bool is_png = !png_sig_cmp(header, 0, number);
		if (!is_png)
		{
			ErrorLogger::getLogger()<<"Error: file not a valid png file : "<<file<<" \n";
		}

		png_structp png_ptr = png_create_read_struct
			(PNG_LIBPNG_VER_STRING, (png_voidp)0,
			0, 0);
		if (!png_ptr)
			ErrorLogger::getLogger()<<"Error when loading png file : "<<file<<" \n";

		png_infop info_ptr = png_create_info_struct(png_ptr);
		if (!info_ptr)
		{
			png_destroy_read_struct(&png_ptr,
				(png_infopp)NULL, (png_infopp)NULL);
			return 0;
		}

		png_infop end_info = png_create_info_struct(png_ptr);
		if (!end_info)
		{
			png_destroy_read_struct(&png_ptr, &info_ptr,
				(png_infopp)NULL);
			return 0;
		}
		if (setjmp(png_jmpbuf(png_ptr)))
		{
			png_destroy_read_struct(&png_ptr, &info_ptr,
				&end_info);
			fclose(fp);
			return 0;
		}

		png_init_io(png_ptr, fp);
		png_set_sig_bytes(png_ptr, 8);
		png_read_info(png_ptr, info_ptr);

		tex->width = png_get_image_width(png_ptr, info_ptr);
		tex->height = png_get_image_height(png_ptr, info_ptr);
		
		if(png_get_color_type(png_ptr,info_ptr) == PNG_COLOR_TYPE_RGB_ALPHA)
		{			
			//if(to->compressTextures)
			//{
			//	tex->internalFormat = COMPRESSED_RGBA_DXT1;
			//	//      tex->internalFormat = RGBA;
			//}
			//else
			//{
			//	tex->internalFormat = RGBA;
			//}
			tex->texFormat = RGBA;
			tex->internalTexFormat = RGBA;
			tex->bpp = 4;

		}
		else
		{//No Alpha
		/*	if(to->compressTextures)
			{
				tex->internalFormat = COMPRESSED_RGB_DXT1;
			}
			else
			{
				tex->internalFormat = RGB8;
			}*/
			tex->internalTexFormat = RGB;
			tex->texFormat = RGB;
			tex->bpp = 3;
		}

		UInt rowBytes = png_get_rowbytes(png_ptr, info_ptr);

		tex->data.resize( rowBytes * tex->height );


		for (UInt row = 0; row < tex->height; row++)
		{
			png_read_row( png_ptr, (unsigned char *)(&tex->data[0]+((tex->height - row - 1)*rowBytes)), NULL );
		}

		png_destroy_read_struct(&png_ptr, &info_ptr,&end_info);

		tex->submitToGPU();
		return tex;


	}

}